package com.itcoon.cloud.framework.transform;

import com.itcoon.cloud.framework.transform.definition.InjectDefinition;
import com.itcoon.cloud.framework.transform.exception.InjectException;
import com.itcoon.cloud.framework.transform.mode.FunctionMode;
import com.itcoon.cloud.framework.transform.mode.InjectMode;
import com.itcoon.cloud.framework.transform.mode.SupplierMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

/**
 * @author Miaoxia Yu
 * @date 2020-10-28
 */
public class InjectHandler {

    private static final Logger log = LoggerFactory.getLogger(InjectHandler.class);

    public InjectDefinition support(String targetAttribute, List<InjectDefinition> injectDefinitions) {
        Optional<InjectDefinition> injectInfoOp = injectDefinitions.stream().filter(injectDefinition -> injectDefinition.getAttribute().equals(targetAttribute)).findAny();
        return injectInfoOp.orElse(null);
    }

    public <T> Object handle(Class<T> targetType, InjectDefinition injectInfo, Object value) {
        InjectMode injectMode = injectInfo.getInjectMode();
        try {
            if (injectMode != null) {
                if (injectMode instanceof SupplierMode) {
                    Supplier<?> supplier = (Supplier<?>) injectMode;
                    return supplier.get();
                } else if (injectMode instanceof FunctionMode) {
                    FunctionMode function = (FunctionMode) injectMode;
                    return function.apply(injectInfo.getSource() == null ? value : injectInfo.getSource());
                }
                throw new InjectException(String.format("injectMode is unSupported, referer attribute#%s.%s", targetType.getSimpleName(), injectInfo.getAttribute()));
            } else {
                return injectInfo.getSource();
            }
        } catch (Exception e) {
            if(e instanceof NullPointerException){
                log.debug("[Transform4j] - inject an null object, targetClass: {}, attribute: {}",targetType.getName(), injectInfo.getAttribute());
                return null;
            }
            log.error("[Transform4j] - can not inject {}.{}, errMsg = {}, ", targetType.getName(), injectInfo.getAttribute(),  e.getMessage());
            throw new InjectException(e.getMessage());
        }
    }
}
